/*
 * Communication.h
 *
 * Created: 11/16/2013 4:26:16 PM
 *  Author: brodzki
 */ 

#ifndef COMM_H_
#define COMM_H_

class IComm
{
protected:
	volatile bool rx_flag;
public:
	// interrupt methods, keep as simple as possible
	virtual void handle_input()			= 0;
	virtual void handle_output()		= 0;
	
	// utilities
	bool was_data_received()
	{
		if(rx_flag)
		{
			rx_flag = false;
			return true;
		}
		else
		{
			return false;
		}
	}
	
	IComm() : rx_flag(false) {}
};

// sender: 1oct, receiver: 1oct, command: 1oct

struct Frame
{
	char sender;
	char receiver;
	char command;
};

class DataFrameComm : public IComm
{
	int field;
	
public:

	Frame received_data;

	DataFrameComm() : field(0) {}

	void handle_input()
	{
		switch(field++)
		{
		case 0:
			received_data.sender = UDR;
			break;
		case 1:
			received_data.receiver = UDR;
			break;
		case 2:
			received_data.command = UDR;
			field = 0;
			rx_flag = true;
			break;
		}
	}
	
	void handle_output()
	{
		
	}
	
	void send_data(Frame &data)
	{
		
	}
};

class NullTerminatedComm : public IComm
{
	volatile int	rx_index;
	volatile int	tx_index;	
	volatile bool	tx_flag;
	char			*tx_buffer;	
	
public:

	char received_data[255];

	NullTerminatedComm() : rx_index(0), tx_index(0), tx_flag(false), tx_buffer(0), received_data() {}	

	void handle_input()
	{
		char rx_data = UDR;
		received_data[rx_index++] = rx_data;
		if(rx_data == '\0')
		{
			rx_flag = true;
			rx_index = 0;
		}
	}
	
	void handle_output()
	{
		if(tx_flag)
		{
			char tx_data = tx_buffer[++tx_index];
			UDR = tx_data;
			if(tx_data == '\0')
			{
				tx_flag = false;
				tx_index = 0;
			}
		}
	}
		
	void send_data(char* data)
	{
		tx_flag = true;
		tx_buffer = data;
		while ( !( UCSRA & (1 << UDRE) ) ) {}
		UDR = tx_buffer[0];
	}
};

#endif // COMM_H_